//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// Program Counter for M8051W/EW
// 
// $Log: m3s009dy.v,v $
// Revision 1.27  2002/03/12
// corrected logic to agree with VHDL, The DATA_POINTER Logic
//
// Revision 1.26  2002/03/12
// changes in the signal MEXSP to be equivalent with the VHDL code
//
// Revision 1.25  2002/01/09
// first clean Verilog for version 2
//
// Revision 1.24  2001/12/24
// V2 tidy ups
//
// Revision 1.23  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.2  2001/10/31
// First parsable verilog for EW
//
// Revision 1.1.1.1  2001/07/17
// Re-imported E-Warp from Farnham filesystem
//
// Revision 1.21  2000/11/30
// Data pointer fix
//
// Revision 1.20  2000/11/21
// Parameterization fix for BankedDataPointers defined to be zero
//
// Revision 1.19  2000/10/24
// Multiplier rewritten to improve power consumption.
// Code changes for Leonardo (ECN01372).
// Code changes for formal verification tools (ECN01410).
// MOVX @Ri page address controllable from PORT2I if I/O ports ommitted (ECN01387).
//
// Revision 1.18  2000/03/03
// FISP BUS option removed
//
// Revision 1.17  2000/02/21
// PROGDI to DPTR timing optimisation
//
// Revision 1.16  2000/02/20
// NINT0/1 sampling and condition zero ALU timing optimisation
//
// Revision 1.15  2000/02/10
// Redundancy reduced for code coverage
//
// Revision 1.14  2000/02/05
// Name change repercussions
//
// Revision 1.13  2000/02/01
// Configuration parameter names standardised
//
// Revision 1.12  2000/01/06
// PROGA no longer cleared during idle mode.
// Minor code tidying up.
//
// Revision 1.11  1999/12/08
// Eliminate user instruction during state transition from interrupt service to
// debug state.
// RTL clean up of redundant declarations and sensitvity list entries.
//
// Revision 1.10  1999/12/07
// *** empty log message ***
//
// Revision 1.9  1999/11/19
// Data pointer bank initialisation fix.
//
// Revision 1.8  1999/11/18
// SFR read enable added, TRAP and DPTR fixes.
//
// Revision 1.7  1999/11/12
// Debug mode fixes
//
// Revision 1.6  1999/11/11
// MappedDataPointers fix
//
// Revision 1.5  1999/11/10
// MappedDataPointers define label fix
//
// Revision 1.4  1999/11/09
// Write PS, TRAP, and EO degugging.
//
// Revision 1.3  1999/11/04
// Sensitivity list corrections.
//
// Revision 1.2  1999/11/03
// Debug mode revisions.
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
// Revision 1.1  1999/10/22
// Initial revision
//
////////////////////////////////////////////////////////////////////////////////
// 
// This module takes four configuration parameters:
//
// `MappedDataPointers : When defined, a second address-mapped data pointer is 
//                       included in the design.
// `BankedDataPointers : When MappedDataPointers is undefined, this defines the 
//                       number of additional datapointers that are included in
//                       the design.
// `sync_pmem          : When defined, the program memory interface is
//                       synchronous, i.e. the PROGA output is unregistered.
// `muxed_pxmem        : When defined, external data memory is accessed using
//                       memory interface signals, XRAMA and XRAMDI are unused.

`include "m8051w_defs.v"
`include "m8051w_cfg.v"


module m3s009dy (PROGA, XRAMA, SAVE_ADDR, MXS_DO, MXS_A, DPTR_SFR_DATA,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                 NPSEN, PROGA_EN, NXRAMW, NXRAMR, NMXSWE, NMXSRE, NPSWR,
                 XRAMA_EN, TRAP, WRPS, DebugVector, ACC, PORT_2, INDIRECT_DATA,
                 INTR_VECTOR, IMMEDIATE, IMMEDIATE_2,
                 CONDITION_MET, EXCEPTION, INTR_LCALL, NEXT_STATE_IDLE, OPCODE,
                 INTERNAL_RESET, REG_RESULT, MXS_DI, DESTIN_ADDR, SFR_WRITE,
                 SFR_S_ADDR, PC_CON, STATE, LAST_CYC, INTERNAL_WAIT, DebugHold,
                 CCLK,
				 CANSEL);

  output [`AddrSize-1:0] PROGA;
  output [`AddrSize-1:0] XRAMA;
  output [7:0]  SAVE_ADDR;
  output [7:0]  MXS_DO;
  output [6:0]  MXS_A;
  output [7:0]  DPTR_SFR_DATA;
  output        NPSEN, PROGA_EN, NXRAMW, NXRAMR, NPSWR, XRAMA_EN;
  output        NMXSWE, NMXSRE;
  output        TRAP, WRPS;
  output        DebugVector;
  output		CANSEL;

  input  [7:0]  ACC, PORT_2, INDIRECT_DATA;
  input  [7:0]  INTR_VECTOR;
  input  [7:0]  IMMEDIATE, IMMEDIATE_2;        // Opcode arguments
  input         CONDITION_MET;                 // branch condition met
  input         EXCEPTION;                     // interrupt next m/c
  input         INTR_LCALL;                    // interrupt LCALL opcode
  input         NEXT_STATE_IDLE;               // Halt program counter
  input  [7:4]  OPCODE;
  input         INTERNAL_RESET;
  input  [7:0]  REG_RESULT;                    // data for SFR ops on DPTR
  input  [7:0]  MXS_DI;
  input  [6:0]  DESTIN_ADDR;
  input         SFR_WRITE;
  input  [6:0]  SFR_S_ADDR;                    // SFR read address
  input  [16:0] PC_CON;                        // opcode decoded controls
  input  [2:0]  STATE;
  input         LAST_CYC, INTERNAL_WAIT;
  input         DebugHold;                     // Freeze PC in debug mode
  input         CCLK;


// Establish the number of data pointers
`ifdef MappedDataPointers
  parameter NoOfDataPointers = 2;
`else
  parameter NoOfDataPointers = (4'b0001 << `BankedDataPointers);
`endif

  reg    [`AddrSize-1:0] L_PROGA;
`ifdef muxed_pxram
  wire   [`AddrSize-1:0] XRAMA;
`else
  reg    [`AddrSize-1:0] XRAMA;
`endif
  reg    [15:0] PROGRAM_COUNT;
  reg    [15:0] DATA_POINTER[0:NoOfDataPointers -1 ];
  wire   [19:0] NEXT_PROGRAM_ADDR;
  reg    [15:0] NEXT_PROGRAM_ADDR16;
`ifdef MemExtend
  reg    [3:0]  NEXT_PROGRAM_BANK;
`else
  wire   [3:0]  NEXT_PROGRAM_BANK;
`endif
  reg    [15:0] NEXT_DATA_POINTER;
  reg    [15:0] OPERAND_16;
  reg    [7:0]  OPERAND_8;
  reg    [7:0]  DPTR_SFR_DATA;
  reg    [4:0]  EOR;
`ifdef MemExtend
  reg    [7:0]  MEX1;
  reg    [7:0]  MEX2;
  reg    [7:0]  MEX3;
  reg    [6:0]  MEXSP;
`else
  wire   [7:0]  MEX1;
  wire   [7:0]  MEX2;
  wire   [7:0]  MEX3;
  wire   [6:0]  MEXSP;
`endif
  wire   [6:0]  NEXT_MEXSP;
  reg           NPSEN, NXRAMW, NXRAMR;
  reg           NPSWR;
`ifdef MemExtend
  reg           NMXSWE, NMXSRE;
`else
  wire          NMXSWE, NMXSRE;
`endif
  reg           INCREMENT, JUMP_RELATIVE, SELECT_DATA_PTR, SELECT_ACC;
  reg           LAST_RESET;
  reg           DebugVector;

  
  assign		CANSEL = EOR[4];

  wire   [15:0] PC_SUM;
  wire   [15:0] CURRENT_DATA_POINTER;
  wire   [15:0] DATA_POINTER_0;
  wire   [15:0] DATA_POINTER_1;
  wire   [7:0]  SAVE_ADDR;                      // Save address for CALLs 
  wire   [2:0]  DPIX;
  wire          WRPS;                           // Write to program strore
  wire          PC_EN, DP_EN, PA_EN, PAX_EN;    // register write enables
  wire          DPL_WRITE;
  wire          DPH_WRITE;
  wire          DPL1_WRITE;
  wire          DPH1_WRITE;
  wire          EOR_WRITE;
  wire          MEX1_WRITE;
  wire          MEX2_WRITE;
  wire          MEX3_WRITE;
  wire          MEXSP_WRITE;


// Instantiate the 16-bit adder/incrementer for the program counter and
// data pointer.

  m3s011dy u1 (.PC_SUM(PC_SUM), .OPERAND_16(OPERAND_16), .OPERAND_8(OPERAND_8),
               .INCREMENT(INCREMENT), .SIGN_EXTEND(JUMP_RELATIVE));

// PC ALU controls
// These controls are registered to break an implied single-cycle path from the
// opcode to the program counter.
// Look ahead logic for program counter incrementer.
// The program counter ALU increments always after an opcode load and 
// speculatively during C1P1 as the opcode decode is not stable in this state.
// The program counter load enables ignore unwanted increments during C1P1 and
// exception LCALLs (see below).
// The PC ALU is also used for incrementing the data pointer.

  always @(posedge CCLK)
  begin: p_pmode
    if (~INTERNAL_WAIT) begin: PC_alu_controls
      SELECT_DATA_PTR <= `C1P1 && (PC_CON[3] || WRPS)                         ||
                         `C1P2 && PC_CON[4];
      SELECT_ACC      <= `C1P1 && (PC_CON[4] || PC_CON[13])                   ||
                         `C1P2 && PC_CON[4];
      INCREMENT       <= LAST_CYC                                             ||
                         `C1P1 && (PC_CON[1] || PC_CON[14] || WRPS) &&
  		                                             !INTR_LCALL      ||
                         `C1P2 && PC_CON[2];
      JUMP_RELATIVE   <= `C1P2 && (PC_CON[8] || PC_CON[7]);
    end
  end

//  PC ALU Input Muxes

  always @(PROGRAM_COUNT or CURRENT_DATA_POINTER or ACC or IMMEDIATE_2 or
           SELECT_DATA_PTR or SELECT_ACC or JUMP_RELATIVE)
  begin: p_PC_operand_muxes
    // Switch PC source to data pointer during cycle 1 for DPTR instructions
    // Otherwise select PC.
    OPERAND_16 <= SELECT_DATA_PTR? CURRENT_DATA_POINTER: PROGRAM_COUNT;

    // Select 8-bit operand: accumulator or relative branch offset.
    OPERAND_8  <= {8{SELECT_ACC}} & ACC | {8{JUMP_RELATIVE}} & IMMEDIATE_2;
  end

//  PC ALU Output MUX

  always @(PC_SUM or IMMEDIATE or IMMEDIATE_2 or INDIRECT_DATA or
           PORT_2 or INTR_VECTOR or PROGRAM_COUNT or OPCODE or PC_CON or STATE
           or INTR_LCALL or CURRENT_DATA_POINTER or WRPS)
  begin: p_PC_output_mux

    if (PC_CON[11] && `C1P2 )                               // RET instructions
      NEXT_PROGRAM_ADDR16 <= {INDIRECT_DATA, 8'h00};
    else if (INTR_LCALL && `C2P1 )                          // Interrupt LCALL
      NEXT_PROGRAM_ADDR16 <= {8'h00, INTR_VECTOR};
    else if (PC_CON[11] && `C2P1 )                          // RET instructions
      NEXT_PROGRAM_ADDR16 <= {PROGRAM_COUNT[15:8], INDIRECT_DATA};
    else if (PC_CON[9] && `C2P1 && ~INTR_LCALL)             // LCALL, LJMPS etc.
      NEXT_PROGRAM_ADDR16 <= {IMMEDIATE, IMMEDIATE_2};
    else if (PC_CON[10] && `C2P1 )                          // ACALLs & AJMPs
      NEXT_PROGRAM_ADDR16 <= {PROGRAM_COUNT[15:11], OPCODE[7:5], IMMEDIATE};
    else if (PC_CON[5] && `C1P1)                            // MOVX @Ri
      NEXT_PROGRAM_ADDR16 <= {PORT_2, INDIRECT_DATA};
    else if ((PC_CON[15] || WRPS) && `C1P1)                 // MOVX @DPTR
      NEXT_PROGRAM_ADDR16 <= CURRENT_DATA_POINTER;
    else
      NEXT_PROGRAM_ADDR16 <= PC_SUM;                          // default is PC ALU

    if (PC_CON[12])                                         // MOV DPTR, #16   
      NEXT_DATA_POINTER <= {IMMEDIATE, IMMEDIATE_2};
    else
      NEXT_DATA_POINTER <= PC_SUM;                          // default is PC ALU
  end
    
`ifdef MemExtend
  // Next Bank output MUX
  always @(MEX1 or MEX2 or MEX3 or PC_CON or STATE or WRPS)
  begin: p_bank_MUX
    // MOVXs load from MX or CB
    if ((PC_CON[5] || PC_CON[15]) && MEX3[3] && `C1P1)
      NEXT_PROGRAM_BANK <= {MEX3[4], MEX3[2:0]};
    // MOVCs load from MB or CB
    else if (MEX2[7] && ((PC_CON[13] && MEX2[7] && `C1P2) || (WRPS && `C1P1)))
      NEXT_PROGRAM_BANK <= {MEX3[7], MEX2[6:4]};
    // default is to use CB
    else
      NEXT_PROGRAM_BANK <= MEX1[7:4];
  end
`endif

// Program register write enables

assign PC_EN = `CLP2 && !NEXT_STATE_IDLE         && !EXCEPTION  && !DebugHold ||
               `C1P1 && PC_CON[0]                && !INTR_LCALL && !DebugHold ||
               `C1P2 && (PC_CON[11]|| PC_CON[1]) && !INTR_LCALL && !DebugHold ||
               `C2P1 && (PC_CON[9] || (PC_CON[2] || PC_CON[4] || PC_CON[8] ||
                        (PC_CON[7] && CONDITION_MET) || PC_CON[10] ||
                        PC_CON[11]) && !DebugHold); 

assign DP_EN = `C1P2 && (PC_CON[14] || WRPS)                                  ||
               `C2P2 && PC_CON[12];
     
assign PA_EN = `CLP2                             && !EXCEPTION  && !DebugHold ||
               `C1P1 && (PC_CON[0])              && !INTR_LCALL && !DebugHold ||
               `C1P2 && (PC_CON[1])              && !INTR_LCALL && !DebugHold ||
               `C2P1 && (PC_CON[2] || PC_CON[4] || PC_CON[8] || PC_CON[10] ||
                         (PC_CON[7] && CONDITION_MET) || PC_CON[11])
                                                                && !DebugHold ||
               `C1P1 && (PC_CON[5] || PC_CON[15] || WRPS)                     ||
               `C1P2 && (PC_CON[13])                                          ||
               `C2P1 && (PC_CON[9] || PC_CON[13] || PC_CON[5] || PC_CON[15] ||
                         PC_CON[6]);

assign PAX_EN =`CLP2                             && !EXCEPTION  && !DebugHold ||
               `C1P1 && (PC_CON[0])              && !INTR_LCALL && !DebugHold ||
               `C1P2 && (PC_CON[1])              && !INTR_LCALL && !DebugHold ||
               `C2P1 && (PC_CON[2] || PC_CON[4] || PC_CON[8] || PC_CON[10] ||
                         PC_CON[7] || PC_CON[11])               && !DebugHold ||
               `C1P1 && (PC_CON[5] || PC_CON[15] || WRPS)                     ||
               `C1P2 && (PC_CON[13])                                          ||
               `C2P1 && (PC_CON[9] || PC_CON[13] || PC_CON[5] || PC_CON[15] ||
                         PC_CON[6]);

  // SFR Write Strobes

  assign DPL_WRITE   = SFR_WRITE && DESTIN_ADDR == `AddrDPL;
  assign DPH_WRITE   = SFR_WRITE && DESTIN_ADDR == `AddrDPH;
  assign EOR_WRITE   = SFR_WRITE && DESTIN_ADDR == `AddrEOR;

`ifdef MemExtend
  assign MEX1_WRITE  = SFR_WRITE && DESTIN_ADDR == `AddrMEX1;
  assign MEX2_WRITE  = SFR_WRITE && DESTIN_ADDR == `AddrMEX2;
  assign MEX3_WRITE  = SFR_WRITE && DESTIN_ADDR == `AddrMEX3;
  assign MEXSP_WRITE = SFR_WRITE && DESTIN_ADDR == `AddrMEXSP;
`endif

`ifdef MappedDataPointers
  assign DPL1_WRITE  = SFR_WRITE && DESTIN_ADDR == `AddrDPL1;
  assign DPH1_WRITE  = SFR_WRITE && DESTIN_ADDR == `AddrDPH1;
`endif

// Program Counter, Data Pointer and Program Address and Extension Registers
// Only the Data Pointer can be written to directly using the regular data path.
// All three registers take data from the Next Program Address bus.

  assign NEXT_PROGRAM_ADDR = {NEXT_PROGRAM_BANK, NEXT_PROGRAM_ADDR16};

  always @(posedge CCLK)
  begin: p_regs
    if (INTERNAL_RESET) begin
      PROGRAM_COUNT <= 0;
      L_PROGA       <= 0;
      EOR           <= 0;
    end
    else if (~INTERNAL_WAIT) begin
      if (PC_EN)
        PROGRAM_COUNT      <= NEXT_PROGRAM_ADDR16;
      if (PA_EN)
        L_PROGA            <= NEXT_PROGRAM_ADDR[`AddrSize-1:0];
      if (EOR_WRITE)
        EOR                <= {REG_RESULT[7],REG_RESULT[4], REG_RESULT[2:0]};
    end
  end

`ifdef MemExtend

  // Bank Registers

  always @(posedge CCLK)
  begin: p_MEX1
    if (INTERNAL_RESET) begin
      MEX1 <= 0;
      MEX2 <= 0;
      MEX3 <= 0;
    end
    else if (~INTERNAL_WAIT) begin
      if (MEX2_WRITE)
        MEX2 <= REG_RESULT;
      if (MEX3_WRITE)
        MEX3 <= REG_RESULT;
      if (`C1P2)
        if (PC_CON[11])
          // Restore MEX1 from stack upon RETurns
          MEX1 <= MXS_DI;
        else if (INTR_LCALL)
          // interrupt loads IB
          MEX1[7:4] <= MEX2[3:0];
        else if (PC_CON[9] || (PC_CON[10] && OPCODE[4]))
          // ACALL, LCALL and LJMP load from NB
          MEX1[7:4] <= MEX1[3:0];
      if (MEX1_WRITE)
        // SFR Write
        MEX1[3:0] <= REG_RESULT[3:0];
    end
  end

  // MEX Stack Pointer

  assign NEXT_MEXSP = MEXSP_WRITE? REG_RESULT[6:0]: MEXSP + {{6{STATE[1]}}, 1'b1};

  always @(posedge CCLK)
  begin: p_MEXSP
    if (INTERNAL_RESET) begin
      MEXSP <= 7'h7f;
      NMXSWE <= 1'b1;
    end
    else if (~INTERNAL_WAIT) begin
      if (MEXSP_WRITE || ((PC_CON[16] || INTR_LCALL) && `C1P1) ||
         (PC_CON[11] && `C2P1))
        MEXSP <= NEXT_MEXSP;
      NMXSWE <= ~((PC_CON[16] || INTR_LCALL) && `C1P1);
    end
  end

  // MEX Stack Memory Strobes
  `ifdef sync_iram
    always @(PC_CON[11] or STATE)
      NMXSRE <= ~(PC_CON[11] && `C1P1);
  `else
    always @(posedge CCLK)
    begin: p_MSXRE
      if (INTERNAL_RESET)
        NMXSRE <= 1'b1;
      else if (~INTERNAL_WAIT)
        NMXSRE <= ~(PC_CON[11] && `C1P1);
    end
  `endif

`endif

  // XRAM address bus

`ifdef muxed_pxram
  assign XRAMA = 0;
`else
  always @(posedge CCLK)
  begin: p_XRAMA
    if (INTERNAL_RESET)
      XRAMA   <= 0;
    else if (~INTERNAL_WAIT) begin
      if ((PC_CON[5] || PC_CON[15]) && `C1P1)
        XRAMA <= NEXT_PROGRAM_ADDR[`AddrSize-1:0];
    end
  end
`endif

  // Data Pointer(s)

  always @(posedge CCLK)
  begin: p_dptrs
    reg [3:0] index;
    if (INTERNAL_RESET) begin
      for (index =0; index < NoOfDataPointers; index = index + 1)
        DATA_POINTER[index] <= 16'h0000;
    end
    else if (~INTERNAL_WAIT)
`ifdef MappedDataPointers
      if (DPH_WRITE)
        DATA_POINTER[0] <= {REG_RESULT, DATA_POINTER_0[7:0]};
      else if (DPL_WRITE)
        DATA_POINTER[0] <= {DATA_POINTER_0[15:8], REG_RESULT};
      else if (DPH1_WRITE)
        DATA_POINTER[1] <= {REG_RESULT, DATA_POINTER_1[7:0]};
      else if (DPL1_WRITE)
        DATA_POINTER[1] <= {DATA_POINTER_1[15:8], REG_RESULT};
`else
      if (DPH_WRITE)
        DATA_POINTER[DPIX] <= {REG_RESULT, CURRENT_DATA_POINTER[7:0]};
      else if (DPL_WRITE)
        DATA_POINTER[DPIX] <= {CURRENT_DATA_POINTER[15:8], REG_RESULT};
`endif
      else if (DP_EN)
        DATA_POINTER[DPIX] <= NEXT_DATA_POINTER;
  end

// The program address output, PROGA, is registered in asynchronous interface
// mode, but is raw next state information for synchronous interface mode.

`ifdef sync_pmem
  assign PROGA = PA_EN? NEXT_PROGRAM_ADDR[`AddrSize-1:0]: L_PROGA;
`else
  assign PROGA = L_PROGA;
`endif

// NXRAMR is the XRAM output enable (tri-state driver)
// NXRAMW is the XRAM write enable
// On the XRAM interface NXRAMR and NXRAW are two clock periods wide (C1P2 and 
// C2P1).  On the multiplexed interface both NXRAMR and NXRAMW 
// are single clock wide signals during C1P2.

  always @(posedge CCLK)
  begin: p_ext_strobes
    if (INTERNAL_RESET) begin
      NPSEN   <= 1;
      NPSWR   <= 1;
      NXRAMR  <= 1;
      NXRAMW  <= 1;
    end
    else if (`C1P1 && ~INTERNAL_WAIT) begin
      NPSEN   <= PC_CON[5] || PC_CON[15] || WRPS;
      NPSWR   <= ~WRPS;
      `ifdef muxed_pxram
        NXRAMR <= ~((PC_CON[5] || PC_CON[15]) && ~OPCODE[4]);
        NXRAMW <= ~((PC_CON[5] || PC_CON[15]) && OPCODE[4]);
      `endif
    end
    else if (`C1P2 && ~INTERNAL_WAIT) begin
      NPSWR   <= 1'b1;
      `ifdef muxed_pxram
        NXRAMR <= 1'b1;
        NXRAMW <= 1'b1;
      `else
        NXRAMR  <= ~((PC_CON[5] || PC_CON[15]) && ~OPCODE[4]);
        NXRAMW  <= ~((PC_CON[5] || PC_CON[15]) && OPCODE[4]);
      `endif
    end
    else if (`C2P1 && ~INTERNAL_WAIT) begin
      NPSEN   <= 1'b0;
    end
    else if (`C2P2 && ~INTERNAL_WAIT) begin
      NXRAMR  <= 1'b1;
      NXRAMW  <= 1'b1;
    end
  end

  always @(posedge CCLK)
  begin: p_debug_states
    LAST_RESET <= INTERNAL_RESET;
    DebugVector <= `C2P1 && (PC_CON[8] || (PC_CON[7] && CONDITION_MET) ||
                    PC_CON[11] || PC_CON[9] || PC_CON[10] || PC_CON[4]); 
  end

  // Multiplex SFR Data

`ifdef MappedDataPointers
  assign DATA_POINTER_0 = DATA_POINTER[0];
  assign DATA_POINTER_1 = DATA_POINTER[1];
`else
  assign DATA_POINTER_0 = CURRENT_DATA_POINTER;
  assign DATA_POINTER_1 = 0;
`endif

  always @(DATA_POINTER_0 or DATA_POINTER_1 or EOR or MEX1 or MEX2 or MEX3 or
           MEXSP or SFR_S_ADDR)
  begin: p_sfr_mux_m
    case (SFR_S_ADDR)
      `AddrDPL :  DPTR_SFR_DATA <= DATA_POINTER_0[7:0];
      `AddrDPH :  DPTR_SFR_DATA <= DATA_POINTER_0[15:8];
      `AddrDPL1:  DPTR_SFR_DATA <= DATA_POINTER_1[7:0];
      `AddrDPH1:  DPTR_SFR_DATA <= DATA_POINTER_1[15:8];
      `AddrEOR :  DPTR_SFR_DATA <= {EOR[4],2'b00, EOR[3], 1'b0, EOR[2:0]};
`ifdef MemExtend
      `AddrMEX1:  DPTR_SFR_DATA <= MEX1;
      `AddrMEX2:  DPTR_SFR_DATA <= MEX2;
      `AddrMEX3:  DPTR_SFR_DATA <= MEX3;
      `AddrMEXSP: DPTR_SFR_DATA <= {1'b0, MEXSP};
`endif
       default:   DPTR_SFR_DATA <= 8'h00;
    endcase
  end

  // Address written to data memory during CALL instructions.
  // The low byte is saved at C1P2 and so has to be taken directly from the 
  // PC ALU.

  assign SAVE_ADDR = STATE[0]? PC_SUM[7:0]: PROGRAM_COUNT[15:8];

  // set up data pointer index of correct field width
`ifdef MappedDataPointers
  assign DPIX = {2'b00, EOR[0]}; 
`else
  //parameter EOR_index = (`BankedDataPointers == 0)? 0: NoOfDataPointers - 1;
  parameter EOR_index = (`BankedDataPointers == 0)? 0: (`BankedDataPointers - 1);
  assign DPIX = (`BankedDataPointers == 0)? 3'b000: 3'b000 | EOR[EOR_index:0];
`endif

  // reassign active data pointer element to avoid part selection into array.
  assign CURRENT_DATA_POINTER = DATA_POINTER[DPIX];

  // Export PROGA and XRAM update enables for external wait state generators
  assign PROGA_EN = PAX_EN && ~INTERNAL_WAIT || ~INTERNAL_RESET && LAST_RESET;
`ifdef muxed_pxram
  assign XRAMA_EN = ~INTERNAL_WAIT && (PC_CON[5] || PC_CON[15]) && `C1P1;
`else
  assign XRAMA_EN = ~INTERNAL_WAIT && (PC_CON[5] || PC_CON[15]) && `C2P1;
`endif

  // Separate TRAP and MOVC (DPTR++), A instructions
  assign TRAP   = EOR[3] && PC_CON[6];
  assign WRPS   = ~EOR[3] && PC_CON[6];

  // Export MEX1 for stack op.s
  assign MXS_DO = MEX1;
  assign MXS_A  = MEXSP;

// Tie off certain signals if Memextend not selected
`ifdef MemExtend
`else
  assign MEX1 = 8'b0;
  assign MEX2 = 8'b0;
  assign MEX3 = 8'b0;
  assign MEXSP = 7'b0;
  assign NEXT_PROGRAM_BANK = 4'b0;
  assign NMXSWE = 1'b0;
  assign NMXSRE = 1'b0;
`endif

endmodule
